const qiniu = require('qiniu')
const axios = require('axios')
const fs = require('fs')

class QiniuManager {
    constructor(accessKey, secretKey, bucket, publicBucketDomain) {
        this.mac = new qiniu.auth.digest.Mac(accessKey, secretKey); // 生成鉴权对象
        this.bucket = bucket

        // 配置类
        this.config = new qiniu.conf.Config();
        this.config.zone = qiniu.zone.Zone_z0; // 空间对应的机房
        this.bucketManager = new qiniu.rs.BucketManager(this.mac, this.config);
        this.publicBucketDomain = publicBucketDomain;
    }

    // 文件上传
    uploadFile(key, localFilePath) {
        const options = {
            scope: this.bucket + ':' + key, // 强制覆盖同名文件
        };
        const putPolicy = new qiniu.rs.PutPolicy(options);
        const uploadToken = putPolicy.uploadToken(this.mac); // 生成token
        const formUploader = new qiniu.form_up.FormUploader(this.config);
        const putExtra = new qiniu.form_up.PutExtra();

        // 上传文件具体操作
        return new Promise((resolve, reject) => {
            formUploader.putFile(uploadToken, key, localFilePath, putExtra, this._handleCallback(resolve, reject))
        })
    }

    // 删除文件
    deleteFile(key) {
        return new Promise((resolve, reject) => {
            this.bucketManager.delete(this.bucket, key, this._handleCallback(resolve, reject))
        })
    }

    // 生成下载的地址
    generateDownloadLink(key) {
        const publicDownloadUrl = this.bucketManager.publicDownloadUrl(this.publicBucketDomain, key);
        return publicDownloadUrl;
    }

    // 下载文件
    async downloadFile(key, downloadPath) {
        const link = this.generateDownloadLink(key)
        const timeStamp = new Date().getTime();
        const url = `${link}?timpstamp=${timeStamp}`
        try {
            const res = await axios({
                url,
                method: 'GET',
                responseType: 'stream',
                headers: {
                    'Cache-Control': 'no-cache'
                }
            })
            const writer = fs.createWriteStream(downloadPath)
            res.data.pipe(writer)
            return new Promise((resolve, reject) => {
                writer.on('finish', resolve)
                writer.on('error', reject)
            })
        } catch (err) {
            return Promise.reject({
                err: err.message
            })
        }
    }

    // 获取文件信息
    getState(key) {
        return new Promise((resolve, reject) => {
            this.bucketManager.stat(this.bucket, key, this._handleCallback(resolve, reject))
        })
    }

    _handleCallback(resolve, reject) {
        return (respErr, respBody, respInfo) => {
            if (respErr) {
                reject({
                    code: -1,
                    body: respErr.message
                });
            }
            if (respInfo.statusCode === 200) {
                resolve({
                    code: 200,
                    body: respBody
                });
            } else {
                reject({
                    code: respInfo.statusCode,
                    body: respBody
                })
            }
        }
    }
}

module.exports = QiniuManager